﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Controls.Metadata;
using System.Windows.Forms;
using SoftwareConsulting.BI11.Studio.InternalServices;
using SoftwareConsulting.BI11.Studio.BasicEntities;
using SoftwareConsulting.Interfaces.BasicEntities;

namespace SoftwareConsulting.BI11.Studio.DataTransfer
{
    /// <summary>
    /// Класс узла передачи данных таблицы BI-11
    /// </summary>
    public class TableDataNode:DataNode
    {
        private IRepository _repository; //репозиторий, с которым работаем
        private ITable _table;//таблица, с которой работаем   

        /// <summary>
        /// Возвращает таблицу, с которой работаем
        /// </summary>
        public ITable Table
        {
            get
            {
                return _table;
            }
        }

        /// <summary>
        /// Записывает данные
        /// </summary>
        /// <param name="records"></param>
        internal override void TransferData(List<object[]> records)
        {
            CallProgress(0);
            Data.Clear();
            Data.AddRange(records);            
            string[] fieldNames = _table.GetColumnNames().ToArray<string>();
            for (int i = 0; i < records.Count; i++)
            {
                object[] record = records[i];
                INamedList nvals = new NamedList();
                for (int j = 0; j < record.Length; j++)
                {
                    nvals.AddValue(fieldNames[j], record[j]);
                }
                _table.AddRow(nvals);
                CallProgress(Convert.ToInt32(Math.Round(((double)i / (double)records.Count) * 100)));
            }
        }

        /// <summary>
        /// Вытягивает записи из таблицы
        /// </summary>
        public void PullRecords()
        {
            CallProgress(0);
            Data.Clear();
            if (_table == null)
            {
                CallProgress(100);
                return;
            }
            int c = _table.GetRowsCount();
            string[] columnNames = _table.GetColumnNames().ToArray<string>();
            for (int i = 0; i < c; i++)
            {
                object[] record = new object[columnNames.Length];
                for (int j = 0; j < columnNames.Length; j++)
                {
                    record[j] = _table.GetValue(columnNames[j], i);
                }
                Data.Add(record);
                CallProgress(Convert.ToInt32(Math.Round(((double)i / (double)c) * 100)));
            }            
        }

        /// <summary>
        /// Создает новую таблицу для работы
        /// </summary>
        /// <param name="fieldTypes">типы полей для новой таблицы</param>
        /// <param name="fieldNames">названия полей для новой таблицы</param>
        public void SetTable(Type[] fieldTypes, string[] fieldNames)
        {
            SetTable(null, fieldTypes, fieldNames);
        }

        /// <summary>
        /// Устанавливает таблицу, с которой работаем
        /// </summary>
        /// <param name="table">существующая таблица</param>
        public void SetTable(ITable table)
        {
            SetTable(table, null, null);
        }

        /// <summary>
        /// Устанавливает таблицу, с которой работаем
        /// </summary>
        /// <param name="table">существующая таблица</param>
        /// <param name="fieldTypes">типы полей для новой таблицы</param>
        /// <param name="fieldNames">названия полей для новой таблицы</param>
        private void SetTable(ITable table, Type[] fieldTypes, string[] fieldNames)
        {
            if (table != null)
            {
                _table = table;
                return;
            }
            if (fieldTypes.Length != fieldNames.Length)
                throw new ArgumentOutOfRangeException();
            MetadataSaveDialog tableSaveDialog = new MetadataSaveDialog();
            RepositoryConnector repositoryConnector = new RepositoryConnector();
            repositoryConnector.SetRepository(_repository);
            tableSaveDialog.RepositoryConnector = repositoryConnector;
            tableSaveDialog.SetInitialContainer(_repository.RootFolder.Descriptor);
            tableSaveDialog.SetKinds(MetadataObjectKind.Table);
            tableSaveDialog.ObjectName = _repository.ProposeNewObjectName(MetadataObjectKind.Table);
            tableSaveDialog.ObjectLabel = _repository.ProposeNewObjectLabel(MetadataObjectKind.Table);
            tableSaveDialog.OverwritePrompt = true;
            if (tableSaveDialog.Execute() == DialogResult.OK)
            {                
                IMetadataObjectDescriptor newTable = _repository.GetObjectDescriptorByLabel(tableSaveDialog.ObjectLabel);
                if (newTable != null)
                {
                    //уже есть такой объект, удаляем его (пользователь разрешил в диалоге)
                    if (!repositoryConnector.DeleteObjects(newTable, null, true))
                    {
                        //пользователь все-таки отменил удаление                        
                        return;
                    }
                    newTable = _repository.GetObjectDescriptorByLabel(tableSaveDialog.ObjectLabel);
                    if (newTable != null)
                    {
                        //пользователь не отменял, но таблица не осилила удалиться (видимо, есть зависимости)                        
                        return;
                    }
                }
                newTable = _repository.CreateObject(
                    MetadataObjectKind.Table,
                    tableSaveDialog.ObjectName,
                    tableSaveDialog.ObjectLabel,
                    string.Empty,
                    tableSaveDialog.ObjectContainer);
                _table = newTable.Bind() as ITable;                               
                for (int i = 0; i < fieldTypes.Length; i++)
                {
                    Core.DBProviders.DataColumnProperties props = new Core.DBProviders.DataColumnProperties()
                    {
                        ToAutoInc = false,
                        ColumnType = fieldTypes[i],
                        IsUniqueValue = false,
                        Name = fieldNames[i]
                    };
                    _table.UpdateOrAddColumn(string.Empty, props, false);
                }                
            }
            SetReady();
        }

        /// <summary>
        /// Конструктор класса
        /// </summary>
        public TableDataNode(IRepository repository)
        {
            _repository = repository;
        }
    }
}
